package com.tengju.bff.interfaces.app.motivation.facade;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.tengju.bff.interfaces.app.motivation.assembler.BonusRankAssembler;
import com.tengju.bff.interfaces.app.motivation.vo.BonusRankDetailVO;
import com.tengju.bff.interfaces.app.motivation.vo.BonusRankVO;
import com.tengju.bff.interfaces.app.motivation.vo.PageBonusRankDetailVO;
import com.tengju.bff.interfaces.shared.KVVO;
import com.tengju.bff.interfaces.shared.RankVO;
import com.tengju.data.domain.model.motivation.DwsBonusTopMonthRepository;
import com.tengju.data.domain.model.motivation.DwsBonusTopYearRepository;
import com.tengju.data.domain.model.report.AchievementBonusDateConfig;
import com.tengju.data.domain.model.service.AchievementBonusDateConfigService;
import com.tengju.data.domain.shared.CastUtil;
import com.tengju.data.domain.shared.DateUtil;
import com.tengju.data.domain.shared.Month;
import com.tengju.support.domain.model.alert.AlertEvent;
import com.tengju.support.domain.model.alert.AlertService;
import com.tengju.user.domain.model.Row;
import com.tengju.user.domain.model.user.UserIdCode;
import com.tengju.user.domain.model.user.UserInfo;
import com.tengju.user.domain.model.user.UserInfoRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.time.LocalDate;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author chenhang
 * @Date 2021/7/19
 */
@Service
@RequiredArgsConstructor(onConstructor_ = {@Autowired})
@Slf4j
public class BonusTopListFacade {

    @Value("${user.headImage.default}")
    private String defaultImage;

    @Value("${app.motivation.rank.top.limit}")
    private Integer topLimit;

    private final DwsBonusTopMonthRepository dwsBonusTopMonthRepository;
    private final DwsBonusTopYearRepository dwsBonusTopYearRepository;
    private final UserInfoRepository userInfoRepository;
    private final AlertService alertService;
    private final AchievementBonusDateConfigService achievementBonusDateConfigService;

    public BonusRankVO rankInfo(UserIdCode userIdCode) {
        if (userIdCode == null) {
            return null;
        }
        BonusRankVO bonusRankVO = new BonusRankVO();
        // 当前年月
        LocalDate ld = LocalDate.now();
        Integer year = ld.getYear();
        Integer lastYear = ld.minusYears(1).getYear();
        Integer month = new Month(ld).getMonthInt();
        Integer lastMonth = new Month(ld).preMonth().getMonthInt();

        // 获取月度日期配置
        AchievementBonusDateConfig dateConfig = achievementBonusDateConfigService.queryByCalDateOrDefault(ld);
        if (!StringUtils.isBlank(dateConfig.getDataKey())) {
            month = Integer.valueOf(dateConfig.getDataKey());
            lastMonth = new Month(month).preMonth().getMonthInt();
        }

        // 个人月度收益排行
        Row selfMonthRow =
                dwsBonusTopMonthRepository.getSelfMonthRank(userIdCode,month,lastMonth,topLimit);
        KVVO<String, RankVO> monthRank = KVVO.of(month % 100 + "月收益TOP365排行榜",
                RankVO.of(CastUtil.castInt(selfMonthRow.getValue("curRank")),
                        CastUtil.castInt(selfMonthRow.getValue("lastRank"))
                ),
                new Month(month).preMonth().getRandomDate().getMonth().getValue()
        );
        bonusRankVO.setMonthRank(monthRank);
        // 个人年度收益
        Row selfYearRow =
                dwsBonusTopYearRepository.getSelfYearRank(userIdCode,year,lastYear,topLimit);
        KVVO<String, RankVO> yearRank = KVVO.of("年度累计收益排行榜",
                RankVO.of(CastUtil.castInt(selfYearRow.getValue("curRank")),
                        CastUtil.castInt(selfYearRow.getValue("lastRank"))
                ),
                ld.minusYears(1).getYear()
        );
        bonusRankVO.setYearRank(yearRank);

        return bonusRankVO;
    }

    public PageBonusRankDetailVO monthRank(Integer month, Integer pageIndex, Integer pageSize) {

        Integer offset = Math.max((pageIndex - 1) * pageSize,0);

        // 获取当前月收益排行总榜
        List<Row> monthRankRowList =
                dwsBonusTopMonthRepository.getAllMonthRank(month,topLimit,offset,pageSize);
        // 获取当前上月信息
        Integer lastMonth = new Month(month).preMonth().getMonthInt();
        List<UserIdCode> userIdCodeList = monthRankRowList.stream()
                .filter(Objects::nonNull)
                .map(v -> v.getValue("id_code"))
                .filter(Objects::nonNull)
                .map(CastUtil::castLong)
                .map(UserIdCode::new)
                .collect(Collectors.toList());
        List<Row> lastMonthRankRowList =
                dwsBonusTopMonthRepository.getByIdCodeAndMonth(userIdCodeList,lastMonth,topLimit);


        return this.getPageBonusRankDetailVO(month,monthRankRowList,lastMonthRankRowList,pageIndex,pageSize);
    }

    public PageBonusRankDetailVO yearRank(Integer year, Integer pageIndex, Integer pageSize) {

        Integer offset = Math.max((pageIndex - 1) * pageSize,0);
        // 去年时间
        LocalDate localDate = DateUtil.formatToLocalDate(year.toString(),DateUtil.DATE_YEAR_FORMAT);
        Integer lastYear = localDate.minusYears(1).getYear();

        // 获取年度收益排行总榜
        List<Row> yearRankRowList =
                dwsBonusTopYearRepository.getAllYearRank(year,topLimit,offset,pageSize);

        // 获取当前上一年排名
        List<UserIdCode> userIdCodeList = yearRankRowList.stream()
                .filter(Objects::nonNull)
                .map(v -> v.getValue("id_code"))
                .filter(Objects::nonNull)
                .map(CastUtil::castLong)
                .map(UserIdCode::new)
                .collect(Collectors.toList());
        List<Row> lastYearRankRowList =
                dwsBonusTopYearRepository.getByIdCodeAndYear(userIdCodeList,lastYear,topLimit);

        return this.getPageBonusRankDetailVO(year, yearRankRowList, lastYearRankRowList, pageIndex, pageSize);
    }

    public BonusRankDetailVO selfMonthRankDetail(UserIdCode userIdCode, Integer month) {
        UserInfo userInfo = userInfoRepository.getByIdCode(userIdCode);
        BonusRankDetailVO bonusRankDetailVO = BonusRankAssembler.userToBonusRankDetail(userInfo,defaultImage);
        if (bonusRankDetailVO == null) {
            return null;
        }

        // 获取上月时间
        Integer lastMonth = new Month(month).preMonth().getMonthInt();

        // 个人月度排行
        Row selfMonthRow =
                dwsBonusTopMonthRepository.getSelfMonthRank(userIdCode,month,lastMonth,topLimit);
        bonusRankDetailVO.setRank(
                RankVO.of(CastUtil.castInt(selfMonthRow.getValue("curRank")),
                CastUtil.castInt(selfMonthRow.getValue("lastRank"))
                )
        );

        return bonusRankDetailVO;
    }

    public BonusRankDetailVO selfYearRankDetail(UserIdCode userIdCode, Integer year) {
        UserInfo userInfo = userInfoRepository.getByIdCode(userIdCode);
        BonusRankDetailVO bonusRankDetailVO = BonusRankAssembler.userToBonusRankDetail(userInfo,defaultImage);
        if (bonusRankDetailVO == null) {
            return null;
        }
        // 去年时间
        LocalDate localDate = DateUtil.formatToLocalDate(year.toString(),DateUtil.DATE_YEAR_FORMAT);
        Integer lastYear = localDate.minusYears(1).getYear();

        // 个人年度排行
        Row selfYearRow =
                dwsBonusTopYearRepository.getSelfYearRank(userIdCode,year,lastYear,topLimit);
        bonusRankDetailVO.setRank(
                RankVO.of(CastUtil.castInt(selfYearRow.getValue("curRank")),
                        CastUtil.castInt(selfYearRow.getValue("lastRank"))
                )
        );

        return bonusRankDetailVO;
    }


    private PageBonusRankDetailVO getPageBonusRankDetailVO(Integer dataInterval,
                                                           List<Row> rankRowList,
                                                           List<Row> lastRankRowList,
                                                           Integer pageIndex,
                                                           Integer pageSize) {

        PageBonusRankDetailVO pageBonusRankDetailVO = new PageBonusRankDetailVO();
        pageBonusRankDetailVO.setPageIndex(pageIndex);
        pageBonusRankDetailVO.setPageSize(pageSize);

        List<BonusRankDetailVO> bonusRankDetailVOList = Lists.newArrayList();
        if (CollectionUtils.isEmpty(rankRowList)) {
            pageBonusRankDetailVO.setBonusRankDetailVOList(bonusRankDetailVOList);
            return pageBonusRankDetailVO;
        }
        // 批量获取用户信息
        Map<Long,UserInfo> userInfoMap = this.batchUserInfo(rankRowList);

        // 获取上一次排名
        Map<Long,Row> lastRankMap = Maps.newHashMap();
        if (CollectionUtils.isNotEmpty(lastRankRowList)) {
            lastRankMap = lastRankRowList.stream()
                    .filter(Objects::nonNull)
                    .collect(Collectors.toMap(k -> CastUtil.castLong(k.getValue("id_code")),
                            v -> v,(v1,v2) -> v1));
        }

        // 获取最新更新时间
        Long timeStamp = (Long) rankRowList.get(0).getValue("updateTime");
        String updateTimeStr =
                DateUtil.formatLocalDateTime(DateUtil.DATE_TIME_MINUTE_FORMAT,DateUtil.parseByMilliSeconds(timeStamp));

        for (Row rankRow : rankRowList) {
            UserInfo userInfo = userInfoMap.get(CastUtil.castLong(rankRow.getValue("id_code")));
            Row lastRow = lastRankMap.get(CastUtil.castLong(rankRow.getValue("id_code")));

            // 收益排行榜存在，但是没有用户信息，异常数据告警
            if (userInfo == null) {
                AlertEvent event = new AlertEvent("收益排行榜数据异常，用户信息不存在");
                event.addItem("idCode",CastUtil.castLong(rankRow.getValue("id_code")));
                event.addItem("dataInterval",dataInterval);
                alertService.alert(event);
                continue;
            }
            BonusRankDetailVO bonusRankDetailVO = BonusRankAssembler.userToBonusRankDetail(userInfo,defaultImage);
            bonusRankDetailVO.setRank(
                    RankVO.of(CastUtil.castInt(rankRow.getValue("curRank")),
                            CastUtil.castInt(lastRow == null ? 0 : lastRow.getValue("curRank"))
                    ));

            bonusRankDetailVOList.add(bonusRankDetailVO);
        }

        pageBonusRankDetailVO.setDataUpdateTime(updateTimeStr);
        pageBonusRankDetailVO.setBonusRankDetailVOList(bonusRankDetailVOList);

        return pageBonusRankDetailVO;
    }

    private Map<Long,UserInfo> batchUserInfo(List<Row> monthRankRowList) {
        if (CollectionUtils.isEmpty(monthRankRowList)) {
            return Maps.newHashMap();
        }
        List<UserIdCode> userIdCodeList = monthRankRowList.stream()
                .filter(Objects::nonNull)
                .map(row -> List.of(new UserIdCode(CastUtil.castLong(row.getValue("id_code")))))
                .flatMap(Collection::stream)
                .filter(Objects::nonNull)
                .distinct()
                .collect(Collectors.toList());
        List<UserInfo> userInfoList = userInfoRepository.batchGetUserInfo(userIdCodeList);
        return userInfoList.stream()
                .filter(Objects::nonNull)
                .collect(Collectors.toMap(v -> v.getUserIdCode().getValue(),v -> v,(v1,v2) -> v1));
    }

}

